/*
 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.org.apache.xalan.internal.xsltc.trax;

import java.util.Iterator;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.XMLEventWriter;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.ext.Locator2;

/**
 * @author Sunitha Reddy
 */

public class SAX2StAXStreamWriter extends SAX2StAXBaseWriter {

    private XMLStreamWriter writer;

    private boolean needToCallStartDocument = false;

    public SAX2StAXStreamWriter() {

    }

    public SAX2StAXStreamWriter(XMLStreamWriter writer) {

        this.writer = writer;

    }

    public XMLStreamWriter getStreamWriter() {

        return writer;

    }

    public void setStreamWriter(XMLStreamWriter writer) {

        this.writer = writer;

    }

    public void startDocument() throws SAXException {

        super.startDocument();
        // Encoding and version info will be available only after startElement
        // is called for first time. So, defer START_DOCUMENT event of StAX till
        // that point of time.
        needToCallStartDocument = true;
    }

    public void endDocument() throws SAXException {

        try {

            writer.writeEndDocument();

        } catch (XMLStreamException e) {

            throw new SAXException(e);

        }

        super.endDocument();

    }

    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

        if (needToCallStartDocument) {
            try {
                if (docLocator == null)
                    writer.writeStartDocument();
                else {
                    try {
                        writer.writeStartDocument(((Locator2) docLocator).getXMLVersion());
                    } catch (ClassCastException e) {
                        writer.writeStartDocument();
                    }
                }

            } catch (XMLStreamException e) {

                throw new SAXException(e);

            }
            needToCallStartDocument = false;
        }

        try {

            String[] qname = { null, null };
            parseQName(qName, qname);
            //Do not call writeStartElement with prefix and namespaceURI, as it writes out
            //namespace declaration.
            //writer.writeStartElement(qname[0], qname[1], uri);
            writer.writeStartElement(qName);

            // No need to write namespaces, as they are written as part of attributes.
            /*if (namespaces != null) {
            
                final int nDecls = namespaces.size();
                for (int i = 0; i < nDecls; i++) {
                    final String prefix = (String) namespaces.elementAt(i);
                    if (prefix.length() == 0) {
                        writer.setDefaultNamespace((String)namespaces.elementAt(++i));
                    } else {
                        writer.setPrefix(prefix, (String) namespaces.elementAt(++i));
                    }
            
                    writer.writeNamespace(prefix, (String)namespaces.elementAt(i));
                }
            
            
            }*/

            // write attributes
            for (int i = 0, s = attributes.getLength(); i < s; i++) {

                parseQName(attributes.getQName(i), qname);

                String attrPrefix = qname[0];
                String attrLocal = qname[1];

                String attrQName = attributes.getQName(i);
                String attrValue = attributes.getValue(i);
                String attrURI = attributes.getURI(i);

                if ("xmlns".equals(attrPrefix) || "xmlns".equals(attrQName)) {

                    // namespace declaration disguised as an attribute.
                    // write it as an namespace

                    if (attrLocal.length() == 0) {

                        writer.setDefaultNamespace(attrValue);

                    } else {

                        writer.setPrefix(attrLocal, attrValue);

                    }

                    writer.writeNamespace(attrLocal, attrValue);

                } else if (attrPrefix.length() > 0) {

                    writer.writeAttribute(attrPrefix, attrURI, attrLocal, attrValue);

                } else {
                    writer.writeAttribute(attrQName, attrValue);
                }

            }

        } catch (XMLStreamException e) {
            throw new SAXException(e);

        } finally {

            super.startElement(uri, localName, qName, attributes);

        }

    }

    public void endElement(String uri, String localName, String qName) throws SAXException {

        try {

            writer.writeEndElement();

        } catch (XMLStreamException e) {

            throw new SAXException(e);

        } finally {

            super.endElement(uri, localName, qName);

        }

    }

    public void comment(char[] ch, int start, int length) throws SAXException {

        super.comment(ch, start, length);
        try {

            writer.writeComment(new String(ch, start, length));

        } catch (XMLStreamException e) {

            throw new SAXException(e);

        }

    }

    public void characters(char[] ch, int start, int length) throws SAXException {

        super.characters(ch, start, length);
        try {

            if (!isCDATA) {

                writer.writeCharacters(ch, start, length);

            }

        } catch (XMLStreamException e) {

            throw new SAXException(e);

        }

    }

    public void endCDATA() throws SAXException {

        try {

            writer.writeCData(CDATABuffer.toString());

        } catch (XMLStreamException e) {

            throw new SAXException(e);

        }

        super.endCDATA();

    }

    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {

        super.ignorableWhitespace(ch, start, length);
        try {

            writer.writeCharacters(ch, start, length);

        } catch (XMLStreamException e) {

            throw new SAXException(e);

        }

    }

    public void processingInstruction(String target, String data) throws SAXException {

        super.processingInstruction(target, data);
        try {

            writer.writeProcessingInstruction(target, data);

        } catch (XMLStreamException e) {

            throw new SAXException(e);

        }

    }

}
